﻿using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Presentation;
using IronPython.Runtime.Operations;
using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils.NPOIHelp;
using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Widgets.MindMap;
using NPOI.OpenXmlFormats.Dml.Spreadsheet;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Crypto.Generators;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils
{
    /// <summary>
    /// 注意：此树型文字表并不会考虑图像链接与文件链接，也不会与当前 Markdown 编辑器绑定，所以无法计算相对路径指向的文件。
    /// 如有此需求，应使用 MindMapView 控件自带的 TreeElement 类。
    /// </summary>
    public class 树型文字表
    {
        public 树型文字表()
        {
            _下级节点集 = new List<树型节点>();
        }

        public 树型文字表(string srcTextLines)
        {
            var txtLines = srcTextLines.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);

            var treeTables = new List<List<string>>();
            List<string> treeTable = null;

            for (int i = 0; i < txtLines.Length; i++)
            {
                var txtLine = txtLines[i];
                if (CustomMarkdownSupport.IsTreeListTextLine(txtLine, out string header, out string tail, out int level, true))
                {
                    if (treeTable == null)
                    {
                        treeTable = new List<string>();
                    }
                    else
                    {
                        if (level == 1)
                        {
                            treeTables.Add(treeTable);
                            treeTable = new List<string>(); // 连续的树型文字表，碰到一级算一个新表
                        }
                    }
                    treeTable.Add(txtLine.TrimStart(new char[] { ';', '；', }));
                }
                else
                {
                    if (treeTable != null && treeTable.Count > 0)
                    {
                        treeTables.Add(treeTable);
                        treeTable = null;
                    }
                }
            }

            // 防止树型文字表是最后一行
            if (treeTable != null && treeTable.Count > 0)
            {
                treeTables.Add(treeTable);
                treeTable = null;
            }

            this._下级节点集 = 转换为根节点列表(this, treeTables);
        }

        /// <summary>
        /// 一个树型文字表可能包括多个根节点，故应返回根节点列表。
        /// 每个根节点（及其下的子级节点）共同构成一幅思维导图。
        /// </summary>
        /// <param name="lines"></param>
        /// <param name="allElements">这个列表不递归，找 FriendElement 时直接循环就可以，效率更高。</param>
        /// <returns>返回的是 RootElements。</returns>
        public static List<树型节点> 转换为根节点列表(树型文字表 treeTxtTable, List<List<string>> treeTables)
        {
            List<树型节点> rootElements = new List<树型节点>();

            树型节点 newRootElement = null;
            树型节点 previewElement = null;
            foreach (var treeTable in treeTables)
            {
                if (treeTable.Count <= 0) continue;
                foreach (var treeLine in treeTable)
                {
                    if (CustomMarkdownSupport.IsTreeListTextLine(treeLine, out string header, out string tail, out int level) == false)
                    {
                        continue;
                    }
                    if (level < 1) continue;

                    if (level == 1)
                    {
                        newRootElement = new 树型节点(treeTxtTable, null, tail, level);
                        rootElements.Add(newRootElement);
                        previewElement = newRootElement;
                        continue;
                    }

                    if (previewElement != null)
                    {
                        if (level == previewElement.节点级别)
                        {
                            if (previewElement.所属节点 != null)
                            {
                                var newElement = new 树型节点(treeTxtTable, previewElement.所属节点, tail, level);
                                previewElement.所属节点.下级节点集.Add(newElement);
                                previewElement = newElement;
                                continue;
                            }
                        }
                        else if (level >= previewElement.节点级别 + 1)
                        {
                            var newElement = new 树型节点(treeTxtTable, previewElement, tail, previewElement.节点级别 + 1);
                            previewElement.下级节点集.Add(newElement);
                            previewElement = newElement;
                            continue;
                        }
                        else
                        {
                            // 级别小于前一个，可能小好几级
                            // 沿着 previewElement 向上找，直到找到级别为 level -1 的那个节点
                            var preParentElement = previewElement.所属节点;
                            while (preParentElement != null && preParentElement.节点级别 > level - 1)
                            {
                                preParentElement = preParentElement.所属节点;
                            }

                            var newElement = new 树型节点(treeTxtTable, preParentElement, tail, level);
                            preParentElement.下级节点集.Add(newElement);
                            previewElement = newElement;
                            continue;
                        }
                    }
                    // 由于树型文字表自带格式化功能，所以理论上，poreviewElement 为 null 的情况只应该是根元素才会碰到
                }
            }

            return rootElements;
        }

        private List<树型节点> _下级节点集;

        public List<树型节点> 下级节点集
        {
            get => _下级节点集;
        }

        public 树型节点 添加节点(string text)
        {
            if (this._下级节点集 == null)
            {
                this._下级节点集 = new List<树型节点>();
            }

            var newNode = new 树型节点(this, null, text, 0);  // 添加新根节点
            this._下级节点集.Add(newNode);
            return newNode;
        }

        public 树型节点 插入节点(int index, string text)
        {
            var newNode = new 树型节点(this, null, text, 0);   // 插入新根节点
            if (this._下级节点集 == null)
            {
                this._下级节点集 = new List<树型节点>
                {
                    newNode
                };
                return newNode;
            }
            else
            {
                this._下级节点集.Insert(index, newNode);
                return newNode;
            }
        }

        public 树型节点 删除指定节点(int index)
        {
            if (this._下级节点集 == null || this._下级节点集.Count == 0) return null;

            if (index < 0 || index >= this._下级节点集.Count)
                throw new Exception("指定位置越界。");

            var node = this._下级节点集[index];
            this._下级节点集.RemoveAt(index);
            return node;
        }

        public void 清除下级节点集()
        {
            this._下级节点集.Clear();
        }

        /// <summary>
        /// 按指定关键词在当前文字表的所有根节点中递归查找匹配的节点。
        /// </summary>
        /// <param name="nodeTitleText">不支持纯空白字符的关键词。</param>
        /// <returns>返回匹配的第一个节点。</returns>
        /// <exception cref="Exception">如果当前关键词全由空白字符构成，会抛出异常。</exception>
        public 树型节点 查找节点(string nodeTitleText)
        {
            if (_下级节点集 == null || _下级节点集.Count == 0) return null;

            nodeTitleText = nodeTitleText.Trim();
            if (string.IsNullOrWhiteSpace(nodeTitleText))
                throw new Exception("不支持查找仅由空白字符构成的关键词。LME 默认树型文字表的节点至少应有一个字符。");

            foreach (var rootNode in _下级节点集)
            {
                var destNode = 树型节点.查找节点(rootNode, nodeTitleText);
                if (destNode != null) return destNode;
            }

            return null;
        }

        public 树型节点 按路径取节点(string nodePath)
        {
            if (_下级节点集 == null || _下级节点集.Count == 0) return null;

            if (string.IsNullOrWhiteSpace(nodePath))
                throw new Exception("路径不能为空或全部都是空白字符（如空格、Tab符等）。");

            var spans = 纯文本处理器.按正则分割(@"(?<=[^\/\\])\/", nodePath);       // 以 / 分割，支持 \/ 转义。

            var pathList = new List<string>();
            foreach (var span in spans)
            {
                if (span.是否匹配文本) continue;

                pathList.Add(span.源文本片段);
            }

            树型节点 preNode = null;
            for (int i = 0; i < pathList.Count; i++)
            {
                if (i == 0)
                {
                    foreach (var subNode in _下级节点集)
                    {
                        if (subNode.节点标题文本.ToLower().Trim() == pathList[i].Trim().ToLower())
                        {
                            preNode = subNode;
                            continue;
                        }
                    }
                }
                else
                {
                    if (preNode == null) return null;

                    var subNodes = preNode.下级节点集;
                    if (subNodes == null || subNodes.Count == 0) return null;

                    foreach (var subNode in subNodes)
                    {
                        if (subNode.节点标题文本.ToLower().Trim().Replace("\\/", "/") == pathList[i].Trim().ToLower())
                        {
                            preNode = subNode;
                            continue;
                        }
                    }
                }
            }

            return preNode;
        }

        private double? _汇总结果;

        public double? 汇总结果
        {
            get => _汇总结果;
        }

        public 树型文字表 汇总各分支数据()
        {
            if (_下级节点集 == null || _下级节点集.Count == 0)
            {
                _汇总结果 = null;
                return this;
            }

            double? sum = null;
            var allNull = true;
            foreach (var rootNode in _下级节点集)
            {
                rootNode.汇总下级数据();
                var val = rootNode.汇总结果;   // 汇总数据后，这个属性值才正确。
                if (val != null && val.HasValue)
                {
                    if (sum == null || sum.HasValue == false)
                    {
                        sum = val.Value;
                    }
                    else
                    {
                        sum += val.Value;
                        allNull = false;
                    }
                }
            }

            if (allNull)
            {
                _汇总结果 = null;
            }
            else
            {
                _汇总结果 = sum;
            }
            return this;
        }

        public static void 取结构化文本(树型节点 node, ref StringBuilder sb, bool startsWithExclamation, string preFix, ref int level, int? maxLevel)
        {
            if (node == null) return;

            if (string.IsNullOrEmpty(preFix)) preFix = "\t";

            var preFixText = "";
            if (level > 0)
            {
                preFixText = 纯文本处理器.重复字符串(preFix, level);
            }

            string valPrefix = "";
            if (maxLevel != null && maxLevel.HasValue)
            {
                valPrefix = 纯文本处理器.重复字符串(preFix, maxLevel.Value - level + 1);   // 至少一个分割前缀。
            }

            var valTxt = "";
            if (node.汇总结果 != null && node.汇总结果.HasValue)
            {
                if (node.下级节点集 != null && node.下级节点集.Count > 0)
                {
                    if (valPrefix != "")
                    {
                        valTxt = valPrefix + node.汇总结果.Value.ToString();  // 这种适合粘贴到 Excel 中
                    }
                    else
                    {
                        valTxt = valPrefix + " = {" + node.汇总结果.Value.ToString() + "}";  // 这种适合粘贴到 LME 编辑器中
                    }

                }
                else
                {
                    if (valPrefix != "")
                    {
                        valTxt = valPrefix + node.汇总结果.Value.ToString();  // 这种适合粘贴到 Excel 中
                    }
                    else
                    {
                        valTxt = valPrefix + " = [" + node.汇总结果.Value.ToString() + "]";  // 这种适合粘贴到 LME 编辑器中
                    }
                }
            }

            var text = (startsWithExclamation ? "！" : "") + preFixText + node.节点标题文本 + valTxt;
            sb.Append(text);
            sb.Append("\r\n");

            level++;

            foreach (var subNode in node.下级节点集)
            {
                取结构化文本(subNode, ref sb, startsWithExclamation, preFix, ref level, maxLevel);
            }

            level--;
        }

        public int 最大级别
        {
            get
            {
                var nodes = 取末梢节点集();
                var maxLevel = 0;
                foreach (var node in nodes)
                {
                    maxLevel = Math.Max(maxLevel, node.节点级别);
                }
                return maxLevel;
            }
        }

        public string 输出结构化文本(bool startsWithExclamation = true, string preFix = "　", bool formatWithMaxLevel = false)
        {
            if (this._下级节点集 == null || this._下级节点集.Count == 0) return "";

            int? maxLevel = null;

            if (formatWithMaxLevel)
            {
                maxLevel = 最大级别;
            }

            var sb = new StringBuilder();
            var level = 0;
            foreach (var rootNode in _下级节点集)
            {
                取结构化文本(rootNode, ref sb, startsWithExclamation, preFix, ref level, maxLevel);
            }
            return sb.ToString();
        }

        private static void 取末梢节点集(树型节点 node, ref List<树型节点> leafNodes)
        {
            if (node == null) return;
            if (leafNodes == null) leafNodes = new List<树型节点>();

            if (node.下级节点集 == null || node.下级节点集.Count == 0)
            {
                leafNodes.Add(node);
                return;
            }
            else
            {
                foreach (var subNode in node.下级节点集)
                {
                    取末梢节点集(subNode, ref leafNodes);
                }
            }
        }

        public List<树型节点> 取末梢节点集()
        {
            if (this._下级节点集 == null || this._下级节点集.Count == 0) return null;

            var list = new List<树型节点>();
            foreach (var node in this._下级节点集)
            {
                取末梢节点集(node, ref list);
            }

            return list;
        }
    }

    public class 树型节点
    {
        /// <summary>
        /// 此构造方法不宜公开。
        /// </summary>
        /// <param name="preParentElement">父节点。</param>
        /// <param name="tail">除引导字符之外的文本。</param>
        /// <param name="level">级别。</param>
        public 树型节点(树型文字表 treeTable, 树型节点 preParentElement, string tail, int level)
        {
            初始化树型节点(treeTable, preParentElement, tail, level);
        }

        private void 初始化树型节点(树型文字表 treeTable, 树型节点 preParentElement, string tail, int level)
        {
            var reg = new Regex(@"[ 　\t]{0,}\=[ 　\t]{0,}[\{\[][ 　\t]{0,}[\d\.]{0,}[ 　\t]{0,}[\}\]][ 　\t]{0,}$");

            if (string.IsNullOrEmpty(tail) == false)
            {
                var match = reg.Match(tail);

                if (match.Success)
                {
                    this._节点文本 = tail.Substring(0, match.Index);

                    var numTxt = match.Value.Trim(new char[] { '=', '{', '}', '[', ']', ' ', '　', '\t' });
                    if (double.TryParse(numTxt, out double num))
                    {
                        this._汇总结果 = num;
                    }
                }
                else
                {
                    this._节点文本 = tail;
                }
            }
            else
            {
                this._节点文本 = "<!--无标题节点-->";
            }

            this._所属节点 = preParentElement;
            this._节点级别 = level;
        }

        public 树型节点 添加节点(string text)
        {
            if (this._下级节点集 == null)
            {
                this._下级节点集 = new List<树型节点>();
            }

            var newNode = new 树型节点(this._所属树型文字表, this, text, this.节点级别 + 1);
            this._下级节点集.Add(newNode);
            return newNode;
        }

        public 树型节点 插入节点(int index, string text)
        {
            var newNode = new 树型节点(this._所属树型文字表, this, text, this.节点级别 + 1);
            if (this._下级节点集 == null)
            {
                this._下级节点集 = new List<树型节点>
                {
                    newNode
                };
                return newNode;
            }
            else
            {
                this._下级节点集.Insert(index, newNode);
                return newNode;
            }
        }

        public 树型节点 删除指定节点(int index)
        {
            if (this._下级节点集 == null || this._下级节点集.Count == 0) return null;

            if (index < 0 || index >= this._下级节点集.Count)
                throw new Exception("指定位置越界。");

            var node = this._下级节点集[index];
            this._下级节点集.RemoveAt(index);
            return node;
        }

        public void 清除下级节点集()
        {
            this._下级节点集.Clear();
        }

        public static 树型节点 查找节点(树型节点 node, string nodeTitleText)
        {
            nodeTitleText = nodeTitleText.Trim();
            if (string.IsNullOrWhiteSpace(nodeTitleText))
                throw new Exception("不支持查找仅由空白字符构成的关键词。LME 默认树型文字表的节点至少应有一个字符。");

            if (node == null) return null;

            if (node.节点标题文本.ToLower() == nodeTitleText.Trim().ToLower())
            {
                return node;
            }

            if (node.下级节点集 == null || node.下级节点集.Count <= 0) return null;

            foreach (var subNode in node.下级节点集)
            {
                var result = 查找节点(subNode, nodeTitleText);
                if (result != null) return result;
            }

            return null;
        }

        /// <summary>
        /// 查找节点时，会自动去除首尾空白字符，且会自动转换为小写匹配。
        /// </summary>
        /// <param name="nodeTitleText">不支持纯空白字符的关键词。</param>
        /// <returns>找到的第一个树型节点。</returns>
        /// <exception cref="Exception">关键词全空白时会抛出异常。</exception>
        public 树型节点 查找节点(string nodeTitleText)
        {
            var result = 树型节点.查找节点(this, nodeTitleText);
            if (result != null) return result;  // 如查当前节点就是

            if (_下级节点集 == null || _下级节点集.Count == 0) return null;

            nodeTitleText = nodeTitleText.Trim();
            if (string.IsNullOrWhiteSpace(nodeTitleText))
                throw new Exception("不支持查找仅由空白字符构成的关键词。LME 默认树型文字表的节点至少应有一个字符。");

            foreach (var rootNode in _下级节点集)
            {
                var destNode = 查找节点(rootNode, nodeTitleText);
                if (destNode != null) return destNode;
            }

            return null;
        }

        /// <summary>
        /// 这是个递归方法，不应由用户手动调用。用户只需要使用节点实例的“汇总下级数据”方法即可更新“汇总结果”只读属性的值。
        /// </summary>
        /// <param name="node">递归节点。</param>
        /// <returns>所有子节点的汇总结果。</returns>
        private static double? 计算节点值(树型节点 node)
        {
            if (node == null) return null;

            if (node.下级节点集 == null || node.下级节点集.Count <= 0)
            {
                return node.汇总结果;  // 这种应返回节点本身的值
            }

            double sum = 0.0;
            var allNull = true;
            foreach (var subNode in node.下级节点集)
            {
                var subValue = 计算节点值(subNode);
                // if (subValue == null || subValue.HasValue == false) return null;  // 只要有一个无效值就返回 null。
                // 这样做不好，应允许某些节点不参与计算！！！
                if (subValue != null && subValue.HasValue)
                {
                    sum += subValue.Value;
                    allNull = false;
                }
            }

            if (allNull)
            {
                return node._汇总结果 = null;
            }
            else
            {
                return node._汇总结果 = sum;
            }
        }

        private double? _汇总结果;
        /// <summary>
        /// 在通过此只读属性获取当前节点汇总值之前，应调用“汇总下级数据”方法计算当前节点的汇总值。
        /// ** 注意：1. 所有有下级的节点都没有自己的值——它们的值都由下级汇总而成；只有无下级节点的节点才能设置值。
        /// **       2. 无下级节点，在节点文本末尾用 =[123.44] 这样的格式设置节点的值；也可以使用“树型文字表”类根据指定路径找到节点，再使用节点的“置汇总值”方法。
        /// </summary>
        public double? 汇总结果
        {
            get => _汇总结果;
        }

        public double? 汇总下级数据()
        {
            return _汇总结果 = 计算节点值(this);
        }

        public 树型节点 置汇总结果(double? dValue)
        {
            this._汇总结果 = dValue;
            return this;
        }

        private 树型文字表 _所属树型文字表;

        public 树型文字表 所属树型文字表
        {
            get { return _所属树型文字表; }
        }

        private int? _节点级别;

        public int 节点级别
        {
            get
            {
                if (_节点级别 != null || _节点级别.HasValue) return _节点级别.Value;

                var sum = 0;
                树型节点 parentNode = this.所属节点;
                while (parentNode != null)
                {
                    sum++;
                    parentNode = parentNode.所属节点;
                }

                return sum;
            }
        }

        public IronPython.Runtime.PythonList 标题路径列表
        {
            get
            {
                var list = new IronPython.Runtime.PythonList();
                list.Insert(0, this.节点标题文本);

                树型节点 parentNode = this.所属节点;
                while (parentNode != null)
                {
                    list.Insert(0, parentNode.节点标题文本);
                    parentNode = parentNode.所属节点;
                }

                return list;
            }
        }

        public string 标题路径字符串
        {
            get
            {
                var list = 标题路径列表;
                if (list == null || list.Count == 0) return "";

                var sb = new StringBuilder();
                foreach (var item in list)
                {
                    var txt = item.ToString();
                    if (txt == null) continue;

                    sb.Append(txt.Replace("/", "\\/"));
                    sb.Append("/");
                }

                return sb.ToString().TrimEnd(new char[] { '/' });  // 移除末尾的 /
            }
        }

        public IronPython.Runtime.PythonList 位置路径列表
        {
            get
            {
                var list = new IronPython.Runtime.PythonList();

                if (this.所属节点 == null)
                {
                    list.Insert(0, this.所属树型文字表.下级节点集.IndexOf(this));
                    return list;
                }

                list.Insert(0, this.所属节点.下级节点集.IndexOf(this));

                树型节点 parentNode = this.所属节点;
                while (parentNode != null)
                {
                    if (parentNode.所属节点 == null)
                    {
                        list.Insert(0, this.所属树型文字表.下级节点集.IndexOf(parentNode));
                        break;
                    }

                    list.Insert(0, this.所属节点.下级节点集.IndexOf(parentNode));
                    parentNode = parentNode.所属节点;
                }

                return list;
            }
        }

        public string 位置索引字符串
        {
            get
            {
                var list = 位置路径列表;
                if (list == null || list.Count == 0) return "";

                var sb = new StringBuilder();
                foreach (var item in list)
                {
                    var txt = item.ToString();
                    if (txt == null) continue;

                    sb.Append(txt.Replace("/", "\\/"));
                    sb.Append("/");
                }

                return sb.ToString().TrimEnd(new char[] { '/' });  // 移除末尾的 /
            }
        }

        private string _节点文本;

        public string 节点文本
        {
            get => _节点文本;
            set => _节点文本 = value;
        }

        /// <summary>
        /// 节点文本末尾可能包括 ={} 或 =[] 这样的需要统计的数字区域。
        /// 本属性可以只返回数字区域前面的文本内容。
        /// </summary>
        public string 节点标题文本
        {
            get
            {
                if (string.IsNullOrEmpty(_节点文本)) return "";

                var regex = new Regex(@"\=[\{\[][\d\.]*?[\}\]][ 　\t]*$");
                var match = regex.Match(this._节点文本);
                if (match.Success)
                {
                    return _节点文本.Substring(0, match.Index).Trim();
                }
                else return _节点文本.Trim();
            }
        }

        private 树型节点 _所属节点;

        public 树型节点 所属节点
        {
            get => _所属节点;
            set
            {
                var oldParent = _所属节点;
                var newParent = value;

                if (oldParent == newParent) return;

                // 移动节点
                if (oldParent == null || oldParent.下级节点集 == null || oldParent.下级节点集.Count == 0)
                {
                    if (newParent.下级节点集 == null)
                        newParent.初始化下级节点集();
                    newParent.下级节点集.Add(this);
                    _所属节点 = value;
                    return;
                }

                var index = oldParent.下级节点集.IndexOf(this);
                if (index >= 0)
                {
                    oldParent.删除指定节点(index);
                    if (newParent.下级节点集 == null)
                        newParent.初始化下级节点集();
                    newParent.下级节点集.Add(this);
                    _所属节点 = value;
                    return;
                }
                _所属树型文字表 = value._所属树型文字表;
                _所属节点 = value;
            }
        }

        private void 初始化下级节点集()
        {
            this._下级节点集 = new List<树型节点>();
        }

        public 树型节点 父节点
        {
            get => _所属节点;
            set => _所属节点 = value;
        }

        private List<树型节点> _下级节点集 = new List<树型节点>();

        public 树型节点 根节点
        {
            get
            {
                if (this._所属节点 == null) return this;  // 自身为根节点

                树型节点 preNode = this._所属节点;
                树型节点 preRealNode = preNode;
                while (preNode != null)
                {
                    preNode = preNode.所属节点;
                    if (preNode != null)
                    {
                        preRealNode = preNode;
                    }
                }

                return preRealNode;
            }
        }

        public bool 是否根节点
        {
            get => this._所属节点 == null ? true : false;
        }

        public List<树型节点> 下级节点集 { get => _下级节点集; }

        public List<树型节点> 子节点集 { get => _下级节点集; }

        public 树型节点 前侧节点
        {
            get
            {
                if (_所属节点 == null || _所属节点.下级节点集 == null || _所属节点.下级节点集.Count <= 0) return null;

                var index = _所属节点.下级节点集.IndexOf(this);

                if (index < 0) return null;

                if (index >= 1)
                {
                    return _所属节点.下级节点集[index - 1];
                }

                return null;
            }
        }

        public List<树型节点> 前侧节点集
        {
            get
            {
                if (_所属节点 == null || _所属节点.下级节点集 == null || _所属节点.下级节点集.Count <= 0) return null;

                var index = _所属节点.下级节点集.IndexOf(this);

                if (index < 0) return null;

                if (index >= 1)
                {
                    var list = new List<树型节点>();

                    for (int i = 0; i < index; i++)
                    {
                        list.Add(_所属节点.下级节点集[i]);
                    }

                    return list;
                }

                return null;
            }
        }

        public 树型节点 后侧节点
        {
            get
            {
                if (_所属节点 == null || _所属节点.下级节点集 == null || _所属节点.下级节点集.Count <= 0) return null;

                var index = _所属节点.下级节点集.IndexOf(this);

                if (index < 0) return null;

                if (index < _所属节点.下级节点集.Count - 1)
                {
                    return _所属节点.下级节点集[index + 1];
                }

                return null;
            }
        }

        public List<树型节点> 后侧节点集
        {
            get
            {
                if (_所属节点 == null || _所属节点.下级节点集 == null || _所属节点.下级节点集.Count <= 0) return null;

                var index = _所属节点.下级节点集.IndexOf(this);

                if (index < 0) return null;

                if (index < _所属节点.下级节点集.Count - 1)  // 后侧至少还有一个节点
                {
                    var list = new List<树型节点>();

                    for (int i = index + 1; i < _所属节点.下级节点集.Count; i++)  // 要包括最后一个节点 .Count - 1
                    {
                        list.Add(_所属节点.下级节点集[i]);
                    }

                    return list;
                }

                return null;
            }
        }

        public List<树型节点> 同级其它节点
        {
            get
            {
                if (_所属节点 == null || _所属节点.下级节点集 == null || _所属节点.下级节点集.Count <= 0) return null;

                var index = _所属节点.下级节点集.IndexOf(this);

                if (index < 0) return null;

                var list = new List<树型节点>();

                for (int i = 0; i < _所属节点.下级节点集.Count; i++)
                {
                    list.Add(_所属节点.下级节点集[i]);
                }
                list.RemoveAt(index);

                return list;
            }
        }

        private static void 取末梢节点集(树型节点 node, ref List<树型节点> leafNodes)
        {
            if (node == null) return;
            if (leafNodes == null) leafNodes = new List<树型节点>();

            if (node.下级节点集 == null || node.下级节点集.Count == 0)
            {
                leafNodes.Add(node);
                return;
            }
            else
            {
                foreach (var subNode in node.下级节点集)
                {
                    取末梢节点集(subNode, ref leafNodes);
                }
            }
        }

        public List<树型节点> 取末梢节点集()
        {
            if (this._下级节点集 == null || this._下级节点集.Count == 0) return null;

            var list = new List<树型节点>();
            foreach (var node in this._下级节点集)
            {
                取末梢节点集(node, ref list);
            }

            return list;
        }
    }
}
